<template>
	<!-- 监听滚动条，滚动条位置改变会提交位置，sc为父级额外样式类
			父组件可以调用scrollTo平滑的加速滚动到指定位置
			触底后触发sole事件，三秒一次
			{name: 存在仓库的名字}
	-->
	<div class="scroll sc" ref="scrolls">
		<slot></slot>
	</div>
</template>

<script>
export default{
	props: {
		name: {
			type: String,
			required: true
		}
	},
	data(){
		return{
			// 防抖，是否可以触发触底事件，三秒一次
			flag: true,
			// 滚动速度，加速滚动
			speed: 0
		}
	},
	computed:{
		// 滚动条滚动位置
		scrollTop(){
			return this.$store.state.global.scrolls[this.name];
		},
		// 滚动条对象
		scroll(){
			return this.$refs.scrolls;
		}
	},
	methods:{
		// 滚动条变化记录和操作，判断是否触底
		handlerScroll(){
			let elem = this.$refs.scrolls,
					name = this.name,
					val = elem.scrollTop,
					sole = elem.scrollHeight - val - 150 < elem.clientHeight;
			// 提交当前scroll的名字位置
			this.$store.commit('global/setScrolls', {name, val});
			// 判断是否触底，三秒钟只触发一次，并且数组加载完成才能再触发
			if(this.flag && sole && !this.$root.loading){
				this.flag = false;
				this.$emit('sole');
				setTimeout(()=>{
					this.flag = true;
				},1000)
			}
		},
		// 根据val让滚动条平滑的加速滚动到指定位置
		scrollTo(val){
			let This = this;
			let speed = val>this.scroll.scrollTop ? 30+this.speed : -30-this.speed;
			function fn(){
				let scrollTop = This.scroll.scrollTop;
				// 如果差值大于一帧，滚动一帧，继续判断滚动，差值小于一帧，滚动结束
				if(Math.abs(val-scrollTop)>Math.abs(speed)){
					This.speed++;
					This.scroll.scrollTop += speed + speed>0 ? This.speed : -This.speed;
					requestAnimationFrame(fn);
				}else{
					This.speed = 0;
					scrollTop = val; 
					return;
				}
			}
			requestAnimationFrame(fn);
		},
		// 监听滚动条
		watchScroll(){
			let elem = this.$refs.scrolls
			elem.addEventListener('scroll', this.handlerScroll, true);
		}
	},
	mounted() {
		this.watchScroll();
	},
	watch:{
		// 每当滚动条位置是顶部时，更正位置
		scrollTop(val){
			if(val == 0){
				this.scroll.scrollTop = 0;
			}
		}
	}
}
</script>

<style scrope>
.scroll{
	width: 100%;
	height: 100%;
	overflow: scroll;
	box-sizing: border-box;
}
</style>
